package cachex

import (
	"gitee.com/zhongguo168a/gocodes/datax"
	"gitee.com/zhongguo168a/gocodes/datax/mapx"
	"gitee.com/zhongguo168a/gocodes/datax/schemax"
)

func (s *Object) ToMap() datax.M {
	s.mutex.Lock()
	r := datax.M{}
	s.toMapByField(nil, r)
	s.mutex.Unlock()
	return r
}
func (s *Object) toMap() datax.M {
	if s.data == nil {
		return nil
	}
	r := datax.M{}
	s.toMapByField(nil, r)
	return r
}
func (s *Object) ToMapByField(fieldMap datax.M) (r datax.M) {
	r = datax.M{}
	s.mutex.Lock()
	s.toMapByField(fieldMap, r)
	s.mutex.Unlock()
	return r
}

// fieldMap等于nil，标识遍历所有字段
func (s *Object) toMapByField(fieldMap datax.M, toMap datax.M) {
	sdata := s.data
	if sdata == nil {
		return
	}

	if fieldMap == nil {
		fieldMap = datax.M{}
		for key := range s.data {
			fieldMap[key] = nil
		}
	}

	switch otyp := s.schemaType.(type) {
	case *schemax.MapType: // 如果字段是Map类型
		switch otyp.Value.(type) {
		case *schemax.ClassType: // 如果Map的值是Class类型
			for fieldName, fieldValue := range fieldMap {
				sval := sdata[fieldName]
				if sval == nil {
					toMap[fieldName] = sval
					continue
				}
				obj := sval.(IObject)
				if fieldValue == nil { // 有字段，但为空，标识拷贝说有
					toMap[fieldName] = obj.toMap()
				} else {
					tm := datax.M{}
					obj.toMapByField(fieldValue.(datax.M), tm)
					toMap[fieldName] = tm
				}
			}
		default: // 如果Map的值是非Class类型；另Map的值不支持Map/Array
			for fieldName, ifValue := range fieldMap {
				isval := sdata[fieldName]
				switch sval := isval.(type) {
				case IObject:
					var sfieldMap map[string]interface{}
					r := datax.M{}
					if ifValue != nil {
						fValue, ok := ifValue.(map[string]interface{})
						if ok {
							sfieldMap = fValue
						}
					}
					sval.toMapByField(sfieldMap, r)
					toMap[fieldName] = r
				case map[string]interface{}:
					if ifValue == nil {
						toMap[fieldName] = mapx.ExportField(sval, nil)
					} else {
						fValue, ok := ifValue.(map[string]interface{})
						if ok {
							toMap[fieldName] = mapx.ExportField(sval, fValue)
						}
					}
				default:
					toMap[fieldName] = sval
				}

			}
		}
	case *schemax.ClassType: // 如果字段是Class类型
		decl := s.schemaDecl
		for fieldName, fieldValue := range fieldMap {
			field := decl.GetField(fieldName)
			sval := sdata[fieldName]
			if sval == nil {
				toMap[fieldName] = sval
				continue
			}
			switch field.Type.(type) {
			case *schemax.ClassType:
				obj := sval.(IObject)

				if fieldValue == nil { // 有字段，但为空，标识拷贝说有
					toMap[fieldName] = obj.toMap()
				} else {
					tm := datax.M{}
					obj.toMapByField(fieldValue.(datax.M), tm)
					toMap[fieldName] = tm
				}
			case *schemax.MapType:
				obj := sval.(IObject)
				if fieldValue == nil { // 有字段，但为空，标识拷贝说有
					toMap[fieldName] = obj.toMap()
				} else {
					tm := datax.M{}
					obj.toMapByField(fieldValue.(datax.M), tm)
					toMap[fieldName] = tm
				}
			case *schemax.ArrayType:
				obj := sval.(IObject)
				if fieldValue == nil { // 有字段，但为空，标识拷贝说有
					toMap[fieldName] = obj.toMap()
				} else {
					tm := datax.M{}
					obj.toMapByField(fieldValue.(datax.M), tm)
					toMap[fieldName] = tm
				}
			default:
				obj, ok := sval.(IObject)
				if ok {
					toMap[fieldName] = obj.toMap()
				} else {
					toMap[fieldName] = sval
				}

			}

		}

	default:

	}

	return
}
